/*  
* Copyright (c) 2010, James Daniello
* This project is licensed under the 'New BSD' license.
* The full text of the license can be found in the root
* directory under the filename "LICENSE"
*/
package src.gui;

import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JComboBox;
import javax.swing.SwingConstants;
import javax.swing.JSeparator;
import javax.swing.JScrollPane;
import javax.swing.JList;
import javax.swing.DefaultListModel;
import javax.swing.ListSelectionModel;
import java.awt.Insets;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.ImageIcon;
import java.awt.Container;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BorderFactory;
import java.awt.BorderLayout;
import java.awt.Font;
import java.util.HashMap;
import java.util.Iterator;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.MouseListener;

public class PICAIUClientGUILogin implements PICAIUGUI{
  
  //The various gui components.
  private Container frame;       //<-- the main panel container
  
  private PICAIUClientGUI parent;
  
  private JPanel north,west,east;
  private JLabel auth;
  
  private JTextField userName;
  private JPasswordField password;
  private JButton login;
  private JLabel registerLabel,recoverLabel,userNameLabel,passwordLabel;
  private JButton recoverLink, registerLink;
  private long lastAuth=System.currentTimeMillis();
  
  private DefaultListModel serversList; 
  private JList list;
  private JComboBox serverComboBox = new JComboBox();
  private boolean removeButtonPressed=false;
  
  //Used for the loading icon at the bottom of the page
  private JLabel loadingPanel;
  private ImageIcon loading;
  private PICAIUDelayedImageIconSetter iconDelay;
  public static boolean hideLoading=false;
  
  
  
  
  /**
  * Creates the gui component for the login screen which can be swapped out on the fly.
  */
  public PICAIUClientGUILogin(Container frameIn, PICAIUClientGUI parentIn){
    frame = frameIn;
    parent = parentIn;
    loadServers();
    initGUI();


  }

  
  /**
  * This method loads all of the servers from the client and puts them into the gui
  */
  public void loadServers(){
    serversList = new DefaultListModel();  
    HashMap<String,Integer> servers = parent.getServers();
    String selectedServer = parent.getSelectedServer();
    
    serverComboBox.addItem("Select Server:");
        
    Iterator i = servers.keySet().iterator();
    while(i.hasNext()){
      String server = i.next().toString();
      int port = servers.get(server);
      serversList.addElement(server+":"+port);
      serverComboBox.addItem(server+":"+port);
    }

  }
  
  /**
  * Adds the specified server into the gui
  * @param server the specified server to add into the gui
  */
  public void addServer(String server){
      serversList.addElement(server);
      serverComboBox.addItem(server);
      saveServers();
  }
  
  /**
  * This method removes the currently selected server in the JList from the gui
  */
  private void removeServerFromList(){
    if(list.getSelectedIndex()==-1){
      return;
    }
    
    removeButtonPressed=true;
    int selectionIndex = list.getSelectedIndex();
    String selection = (String)list.getSelectedValue();
    if(serversList.getSize()>=selectionIndex){
      serversList.remove(selectionIndex);
    }
    serverComboBox.removeItem(selection);
    
    parent.removeServer(selection.substring(0,selection.indexOf(":")));
    removeButtonPressed=false;
    saveServers();
  }


  private void saveServers(){
    parent.getClient().saveServerList();
  }

  /**
  * creates the gui components
  */
  public void initGUI(){
    
    //add components to frame
    north = new JPanel();
    //north.setBackground(Color.YELLOW);
    JLabel logo = new JLabel(":: PICAIU ::");
    Font f = new Font("Dialog", Font.PLAIN, 36);
    logo.setFont(f);
    north.add(logo);
    
    west = new JPanel();
    //west.setBackground(Color.RED);
    JPanel padding1 = new JPanel();
    padding1.setSize(376,50);
    padding1.setPreferredSize(new java.awt.Dimension(376,50));
    padding1.setMaximumSize(new java.awt.Dimension(376,50));
    padding1.setMinimumSize(new java.awt.Dimension(376,50));
    west.add(padding1);
    
    JPanel logPanel = new JPanel(new GridBagLayout());
    GridBagConstraints constraints = new GridBagConstraints();
    
    constraints.gridx=0;
    constraints.gridy=0;
    userNameLabel =new JLabel("     Corp: ");
    logPanel.add(userNameLabel,constraints);
    userName = new JTextField();
    userName.setColumns(23);
    userName.addKeyListener(new KeyListener(){
      public void keyTyped(KeyEvent e) {}
      public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==10){
          login.setEnabled(false);
          password.setEnabled(false);
          userName.setEnabled(false);
          hideLoading=false;
          Thread t = new Thread(iconDelay);
          t.start();
          auth();
        }
      }
      public void keyReleased(KeyEvent e) {}
    });
    constraints.gridx=1;
    logPanel.add(userName,constraints);
    
    constraints.gridx=0;
    constraints.gridy=1;
    passwordLabel=new JLabel("     Pass: ");
    logPanel.add(passwordLabel,constraints);
    password = new JPasswordField();
    password.setColumns(23);
    password.addKeyListener(new KeyListener(){
      public void keyTyped(KeyEvent e) {}
      public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==10){
          login.setEnabled(false);
          password.setEnabled(false);
          userName.setEnabled(false);
          hideLoading=false;
          Thread t = new Thread(iconDelay);
          t.start();
          auth();
        }
      }
      public void keyReleased(KeyEvent e) {}
    });
    constraints.gridx=1;
    constraints.gridy=1;
    logPanel.add(password,constraints);
      
    west.add(logPanel);
    
    west.add(new JLabel("    "));
  
  
  
    
    
    auth = new JLabel("                                     "+
                      "                                     ");
    auth.setForeground(Color.red);
    west.add(auth);
    login = new JButton("Login");
    login.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent evt){ 
        login.setEnabled(false);
        password.setEnabled(false);
        userName.setEnabled(false);
        hideLoading=false;
        Thread t = new Thread(iconDelay);
        t.start();
        auth();
      }
    });
    
    west.add(login);
    
    
    JPanel padding2 = new JPanel();
    padding2.setSize(376,50);
    padding2.setPreferredSize(new java.awt.Dimension(376,50));
    padding2.setMaximumSize(new java.awt.Dimension(376,50));
    padding2.setMinimumSize(new java.awt.Dimension(376,50));
    west.add(padding2);
    registerLabel = new JLabel("                        ");
    west.add(registerLabel);
    
    registerLink = new JButton();
    registerLink.setHorizontalTextPosition(SwingConstants.LEFT);
    registerLink.setText("<HTML><FONT color='#000099'><U>here</U></FONT></HTML>");
    registerLink.setBorder(BorderFactory.createEmptyBorder());
    registerLink.setMargin(new Insets(0,0,0,0));  
    registerLink.setOpaque(false);
    registerLink.setBackground(new Color(234,234,234));
    registerLink.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        parent.setGUI("registration");
      }
    });
    west.add(registerLink);
    
    recoverLabel = new JLabel("                                    ");
    west.add(recoverLabel);
    recoverLink = new JButton();
    recoverLink.setHorizontalTextPosition(SwingConstants.LEFT);
    recoverLink.setText("<HTML><FONT color='#000099'><U>here</U></FONT></HTML>");
    recoverLink.setBorder(BorderFactory.createEmptyBorder());
    recoverLink.setMargin(new Insets(0,0,0,0));  
    recoverLink.setOpaque(false);
    recoverLink.setBackground(new Color(234,234,234));
    recoverLink.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        parent.setGUI("recover");
      }
    });
    west.add(recoverLink);
    
    west.setSize(new java.awt.Dimension(376,450));
    west.setPreferredSize(new java.awt.Dimension(376,450));
    west.setMinimumSize(new java.awt.Dimension(376,450));
    west.setMaximumSize(new java.awt.Dimension(376,450));
    
    JPanel panel = new JPanel();
    panel.setSize(new java.awt.Dimension(376,150));
    panel.setPreferredSize(new java.awt.Dimension(376,150));
    panel.setMinimumSize(new java.awt.Dimension(376,150));
    panel.setMaximumSize(new java.awt.Dimension(376,150));
    west.add(panel);
    loadingPanel = new JLabel("                                                "+
    "                                                                ");
    loading = new ImageIcon("res/images/loading.gif");
    loadingPanel.setIcon(loading);
    iconDelay = new PICAIUDelayedImageIconSetter(loadingPanel,loading,500);
    west.add(loadingPanel);
    
    
    east = new JPanel();
    
    JPanel padding3 = new JPanel();
    padding3.setSize(376,50);
    padding3.setPreferredSize(new java.awt.Dimension(376,50));
    padding3.setMaximumSize(new java.awt.Dimension(376,50));
    padding3.setMinimumSize(new java.awt.Dimension(376,50));
    east.add(padding3);
    
    //load server list
    serverComboBox.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        if(removeButtonPressed){
          removeButtonPressed=false;
        }else{
          JComboBox cb = (JComboBox)e.getSource();
          String selection = (String)cb.getSelectedItem();
          if(serverComboBox.getItemAt(0).equals("Select Server:")&&serverComboBox.getItemCount()!=1){
            serverComboBox.removeItemAt(0);
          }
          if(selection!=null&&!selection.equals("Select Server:")){
              connectAndCleanUp(selection);
          }
        }
      }
    });
    serverComboBox.setSize(260,20);
    serverComboBox.setBackground(Color.YELLOW);
    serverComboBox.setPreferredSize(new java.awt.Dimension(260,20));
    serverComboBox.setMaximumSize(new java.awt.Dimension(260,20));
    serverComboBox.setMinimumSize(new java.awt.Dimension(260,20));
    east.add(serverComboBox);
    
    list = new JList(serversList);
    list.setSize(242,268);
    list.setPreferredSize(new java.awt.Dimension(242,268));
    list.setMaximumSize(new java.awt.Dimension(242,268));
    list.setMinimumSize(new java.awt.Dimension(242,268));
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    list.addMouseListener(new MouseListener(){

            public void mouseClicked(MouseEvent e) {
                if(e.getClickCount()==2&&e.getButton()==1){
                    serverComboBox.setSelectedItem(list.getSelectedValue());
                }
            }

            public void mousePressed(MouseEvent e) {}
            public void mouseReleased(MouseEvent e) {}
            public void mouseEntered(MouseEvent e) {}
            public void mouseExited(MouseEvent e) {}
    }
    );


    JScrollPane serverScrollPane = new JScrollPane(list);
    serverScrollPane.setSize(260,270);
    serverScrollPane.setPreferredSize(new java.awt.Dimension(260,270));
    serverScrollPane.setMaximumSize(new java.awt.Dimension(260,270));
    serverScrollPane.setMinimumSize(new java.awt.Dimension(260,270));
    east.add(serverScrollPane);
    
    JPanel serverButtons = new JPanel();
    serverButtons.add(new JLabel("                                      "));
    
    JButton addServerButton = new JButton("Add");
    addServerButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        parent.setGUI("add server");
      }
    });
    serverButtons.add(addServerButton);
    
    JButton removeServerButton = new JButton("Remove");
    removeServerButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        
        removeServerFromList();
      }
    });
    serverButtons.add(removeServerButton);
    
    east.add(serverButtons);
    
    
    east.setSize(new java.awt.Dimension(376,450));
    east.setPreferredSize(new java.awt.Dimension(376,450));
    east.setMinimumSize(new java.awt.Dimension(376,450));
    east.setMaximumSize(new java.awt.Dimension(376,450));
    

    if(serverComboBox.getItemAt(0)==null||((String)serverComboBox.getItemAt(0)).equals("Select Server:")){
      disableLogin();
    }else{
      connectAndCleanUp((String)serverComboBox.getItemAt(0));
    }
  }
  
  /**
  * This method lets the user know that their authentication information was incorrect.
  */
  public void incorrectAuth(){ 
    auth.setText("                         Invalid user/pass.                ");
    enableLogin();
    password.setText("");
    hideLoading=true;
    loadingPanel.setIcon(null);
    password.requestFocus();

  } 
  
  /**
  * Disables the login fields
  */
  protected void disableLogin(){
    userName.setEnabled(false);
    userNameLabel.setForeground(Color.lightGray);
    password.setEnabled(false);
    passwordLabel.setForeground(Color.lightGray);
    login.setEnabled(false);
    registerLabel.setText("");
    registerLink.setVisible(false);
    recoverLabel.setText("");
    recoverLink.setVisible(false);
    auth.setText("                                     "+
                      "                                     ");

  }
  
  /**
  * Enables the login fields
  */
  protected void enableLogin(){
    userName.setEnabled(true);
    userName.setBackground(Color.white);
    userNameLabel.setForeground(Color.darkGray);
    password.setEnabled(true);
    passwordLabel.setForeground(Color.darkGray);
    password.setBackground(Color.white);
    login.setEnabled(true);
    registerLabel.setText("Not Registerd? Register");
    registerLink.setVisible(true);
    recoverLabel.setText("Forgot Login? Recover/Reset Password");
    recoverLink.setVisible(true);
    userName.requestFocus();
  }
  
  /**
  * Selects the item from the combo box as the server to connect to. It then removes all from the 
  * list and adds them all except the one specified by the parameter
  * @param selection the host which will not be added to the serversList
  */
  private void connectAndCleanUp(String selection){
  
    parent.updateSelectedServer(selection.substring(0,selection.indexOf(":")));
    //serversList.remove(cb.getSelectedIndex());
    serversList.removeAllElements(); 
  
    HashMap<String,Integer> servers = parent.getServers();
    
    Iterator i = servers.keySet().iterator();
    while(i.hasNext()){
      String server = i.next().toString();
      int port = servers.get(server);
      if(!(server+":"+port).equals(selection)){
        serversList.addElement(server+":"+port);
      }
    }
  }
  
  /**
  * Retrieves the data from the fields for username and password and sends them to the server for authentication
  */
  private void auth(){
    auth.setText("                                     "+
                      "                                     ");
    if(serverComboBox.getItemAt(0)==null){
        lastAuth=System.currentTimeMillis();
        return;
    }

    if(System.currentTimeMillis()-lastAuth>1000){
      if(!userName.equals("")){
        String pass = parent.getClient().md5(new String(password.getPassword()).replaceAll("#",""));
        parent.getClient().authenticate(userName.getText().replaceAll("#",""),pass);
        pass = "                                   ";
        pass = null;
      }
      lastAuth=System.currentTimeMillis();
    }
  }
  
  /**
  * Sets the 'username/corp' field
  */
  public void setUser(String userIn){
    userName.setText(userIn);
  }
  
  /**
  * This method switches the clients main container to this GUI's graphics.
  */
  @Override 
  public void setAsGUI(){
  
    frame.removeAll();
    
    loadingPanel.setIcon(null);
    frame.add(north,BorderLayout.NORTH);
    frame.add(west,BorderLayout.WEST);
    frame.add(new JSeparator(JSeparator.VERTICAL),BorderLayout.CENTER);
    frame.add(east,BorderLayout.EAST);
    
    
    
    frame.validate();

    if(serverComboBox.getItemAt(0)==null||((String)serverComboBox.getItemAt(0)).equals("Select Server:")){
      disableLogin();
    }else{
      connectAndCleanUp((String)serverComboBox.getItemAt(0));
    }
  }

  /**
  * This sets the colors of all the components affected by the color scheme to that of the current 
  * colors for the GUI
  */
  @Override
  public void setColors(PICAIUGUIScheme colorScheme){
    
    Color colorBG01=colorScheme.getBG01();
    Color colorBG02=colorScheme.getBG02();
    Color colorFG01=colorScheme.getFG01();
    Color colorBorder01=colorScheme.getBorder01();
  
  }

  protected void setPassAsFocus() {
    password.requestFocusInWindow();
  }

  protected void setUserAsFocus(){
    userName.requestFocusInWindow();
  }

}